/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.tencent.tendon.convert.json;

import java.util.Collections;
import java.util.List;

/**
 * 序列化时给对象字段的操作接口， 一个字段一个JsonEnHandle
 *
 * @author nbzhang
 */
public final class JsonEnHandle<T, V> extends JsonHandle<T, V> {

	public static final JsonEnHandle<Object, Object> NULL = new JsonEnHandle(null, null);

	private final char[] field3;

	private final char[] field4;

	protected JsonEnHandle<T, ?> next;

	protected JsonEncodable<V> encoder;

	JsonEnHandle(final JsonAttribute<T, V> attribute, JsonEncodable<V> encoder) {
		super(attribute);
		this.field3 = JsonFactory.fieldQutoable ? ('"' + this.field + "\":").toCharArray() : (this.field + ":").toCharArray();
		this.field4 = JsonFactory.fieldQutoable ? (",\"" + this.field + "\":").toCharArray() : ("," + this.field + ":").toCharArray();
		this.next = null;
		this.encoder = encoder;
	}

	public static <T, V> JsonEnHandle<T, V> create(final JsonAttribute attribute, final JsonEncodable printer) {
		return new JsonEnHandle(attribute, printer);
	}

	static JsonEnHandle link(final List<JsonEnHandle> handles) {
		if (handles.isEmpty()) return JsonEnHandle.NULL;
		Collections.sort(handles);
		JsonEnHandle head = null;
		int index = 0;
		for (JsonEnHandle handle : handles) {
			if (head != null) {
				head.next = handle;
			}
			handle.index(index++);
			head = handle;
		}
		return handles.get(0);
	}

	public boolean writeValue(final JsonWriter out, final boolean comma, final T obj) {
		V value = attribute.get(obj);
		if (value == null) return comma;
		out.write(comma ? field4 : field3);
		encoder.convertTo(out, value);
		return true;
	}

	@Override
	public final boolean isSimpled() {
		return encoder.isSimpled();
	}

	@Override
	public final JsonEnHandle<T, ?> next() {
		return this.next;
	}

	@Override
	public String toString() {
		return "{field:" + String.format("%12s", this.field) + ", encoder:" + String.format("%25s", (encoder.isSimpled() ? encoder.toString() : encoder.getClass().getSimpleName())) + ", attribute:"
			+ String.format("%32s", attribute.toString()) + ", \r\n   next:" + this.next + "}";
	}
}
